<?xml version="1.0"?>
<ruleset name="PHP_CodeSniffer">
    <description>PHP_CodeSniffer configuration</description>
    <arg name="colors"/>
    <arg value="p"/>
    <arg value="s"/>
    <arg name="report" value="code"/>
    <arg name="extensions" value="php"/>
    <arg name="ignore" value="*/vendor*/"/>

    <rule ref="PSR12"/>

    <config name="installed_paths" value="vendor/slevomat/coding-standard"/>

    <!--
    Обнаруживает бесполезные тернарные операторы.

    Пример:
    # Плохо
    $value = ($condition) ? $result1 : $result2;
    if ($condition) {
        $value = $result1;
    } else {
        $value = $result2;
    }

    # Хорошо
    $value = ($condition) ? $result1 : $result2;
    -->
    <rule ref="SlevomatCodingStandard.ControlStructures.UselessTernaryOperator"/>

    <!--
    Обнаруживает лишние условия if с последующим оператором return.

    Пример:
    # Хорошо
    function myFunction($value) {
        if ($value === null) {
            return;
        }

        // код, выполняемый, если $value не равно null
    }

    # Плохо
    function myFunction($value) {
        if ($value === null) {
            return;
        } else {
            // код, выполняемый, если $value не равно null
            return;
        }
    }
    -->
    <rule ref="SlevomatCodingStandard.ControlStructures.UselessIfConditionWithReturn"/>

    <!--
    В PHP 7.1+ можно объявлять видимость констант класса. Подобно необязательному объявлению видимости для свойств и
    методов, которое фактически требуется в нормальных стандартах кодирования, этот фрагмент также требует объявления
    видимости для всех констант класса.

    Пример:
    const FOO = 1; // visibility missing!
    public const BAR = 2; // correct
    -->
    <rule ref="SlevomatCodingStandard.Classes.ClassConstantVisibility"/>

    <!--
    Обеспечивает использование сокращенных вариантов скалярных подсказок в phpDocs:
    int вместо integer и bool вместо boolean. Это сделано для обеспечения совместимости с собственными скалярными
    подсказками, которые также допускают только сокращенные варианты.

    Пример:
    /**
     * @param array $s
     * @param integer $bn // ERROR Expected "int" but found "integer" in @param annotation.
     *
     * @return array
     */

    /**
     * @param array $s
     * @param int $bn
     *
     * @return array
     */
    -->
    <rule ref="SlevomatCodingStandard.TypeHints.LongTypeHints"/>

    <!--
    Проверяет, присутствует ли символ "?" перед каждым и необязательным
    параметром (которые помечены как = null)

    Пример:
    function get(
        int $foo = null, // ERROR Parameter $foo has null default value, but is not marked as nullable.
        ?int $bar = null
    ) {
        ....
    }
    -->
    <rule ref="SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue"/>

    <!--
    Проверяет наличие одного пробела между подсказкой и именем параметра:Foo $foo
    Проверяет, нет ли пробелов между символом, допускающим значение NULL, и подсказкой:?Foo

    Пример:
    1. public function myFunction(string$param1, int$param2): void // ERROR
    1. public function myFunction(string  $param1, int  $param2): void // ERROR
    -->
    <rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHintSpacing"/>

    <!--
    Запрещает использование переменных переменных.

    Пример:
    //ERROR Use of variable variable is disallowed.
    $varName = 'myVariable';
    $$varName = 'Hello, world!';
    -->
    <rule ref="SlevomatCodingStandard.Variables.DisallowVariableVariable"/>

    <!--
    Ищет не используемые переменные

    Пример:
    function get() {
        $result = 1; // ERROR Unused variable $varName

        return 1;
    }
    -->
    <rule ref="SlevomatCodingStandard.Variables.UnusedVariable">
        <exclude-pattern>install/version.php</exclude-pattern>
    </rule>

    <!--
    Запрещает использование свободных операторов ==и !=операторов сравнения. Вместо этого используйте === или !==,
    они гораздо более безопасны и предсказуемые.

    Пример:
    if($a == $b) ERROR [x] Operator == is disallowed, use === instead
    -->
    <rule ref="SlevomatCodingStandard.Operators.DisallowEqualOperators"/>

    <!--
    Запрещает использование синтаксиса подсказки типа массива (например int[], , bool[][])
    в phpDocs в пользу синтаксиса подсказки общего типа (например, array<int>, array<array<bool>>).
    -->
    <rule ref="SlevomatCodingStandard.TypeHints.DisallowArrayTypeHintSyntax"/>

    <!--
    Обеспечивает единообразное форматирование возвращаемых типовых указаний.

    Пример:
    function foo(): ?int
    -->
    <rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHintSpacing"/>

    <!--
    Запрещено использовать обратную косую черту в операторе use.

    Пример:

    # Плохо
    use \Foo\Bar;

    # Хорошо
    use Foo\Bar;
    -->
    <rule ref="SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash"/>

    <!--
    Тернарный оператор необходимо переформатировать, если оператор не возглавляет строку.

    Привет:
    # плохо
    $t = $someCondition ?
        $thenThis :
        $otherwiseThis;

    # хорошо
    $t = $someCondition
        ? $thenThis
        : $otherwiseThis;
    -->
    <rule ref="SlevomatCodingStandard.ControlStructures.DisallowTrailingMultiLineTernaryOperator"/>

    <!--
    Если это возможно, требуется короткий тернарный оператор ?:

    Пример:
    # плохо
    $var = $a ? $a : 45

    # хорошо
    $var = $a ?: 45
    -->
    <rule ref="SlevomatCodingStandard.ControlStructures.RequireShortTernaryOperator"/>

    <!--
    Обеспечивает максимальную когнитивную сложность функций.

    Sniff предоставляет следующие настройки:
        - warningThreshold: по умолчанию 6
        - errorThreshold: по умолчанию 6
    -->
    <rule ref="SlevomatCodingStandard.Complexity.Cognitive"/>

    <!--Документация методов -->
    <rule ref="Squiz.Commenting.FunctionComment">
        <properties>
            <!--Должно пропускать ошибку наследованной документации -->
            <property name="skipIfInheritdoc" value="true"/>

            <!--Включена проверка только у public и protected методов -->
            <property name="minimumVisibility" value="protected"/>
        </properties>

        <!-- Отключена проверка описания метода -->
        <exclude name="Squiz.Commenting.FunctionComment.MissingParamComment"/>

        <!-- Отключена проверка на не понятная что, но она мешает когда в phpdoc все хорошо -->
        <exclude name="Squiz.Commenting.FunctionComment.SpacingAfterParamType"/>
        <exclude name="Squiz.Commenting.FunctionComment.MissingParamTag"/>
        <exclude name="Squiz.Commenting.FunctionComment.EmptyThrows"/>

        <!-- Данная настройка заменена на SlevomatCodingStandard.TypeHints.LongTypeHints -->
        <exclude name="Squiz.Commenting.FunctionComment.IncorrectParamVarName"/>

        <exclude name="Squiz.Commenting.FunctionComment.InvalidReturn"/>

        <!-- Исключение для магических методов -->
        <exclude name="Squiz.Commenting.FunctionComment.Missing">
            <message>Missing doc comment for function</message>
            <source>.*__.*</source>
        </exclude>
    </rule>

    <!-- Проверка на логические операторы "and" и "or", например if (1 and 2) плохо, а if (1 && 2) хорошо  -->
    <rule ref="Squiz.Operators.ValidLogicalOperators"/>

    <!-- Проверка на присутствие мертвого кода  -->
    <rule ref="Squiz.PHP.NonExecutableCode"/>

    <!-- Проверка на применение $this в статических методах  -->
    <rule ref="Squiz.Scope.StaticThisUsage"/>

    <!-- Проверка на двойные кавычки, пример "example" нельзя, а "example {$param}" и 'example' можно  -->
    <rule ref="Squiz.Strings.DoubleQuoteUsage.NotRequired"/>

    <!--
        Проверка на пробел после приведение типов

        Пример:

        # Хорошо
        $hoge = (int) '123';

        # Плохо
        $fuga = (int)'123'; // Expected 1 space(s) after cast statement; 0 found
    -->
    <rule ref="Generic.Formatting.SpaceAfterCast"/>

    <!--
        Проверяет интервал после оператора !

        Пример:

        # Плохо
        $hoge = ! true; // Expected 1 space(s) after NOT operator; 0 found

        # Хорошо
        $fuga = !true;
    -->
    <rule ref="Generic.Formatting.SpaceAfterNot">
        <properties>
            <property name="spacing" value="0"/>
        </properties>
    </rule>

    <!-- Проверка, что нет пустой строки после открывающей фигурной скобки метода -->
    <rule ref="Squiz.WhiteSpace.FunctionOpeningBraceSpace"/>

    <!-- Проверка на присутствие пустых строк до и после метода -->
    <rule ref="Squiz.WhiteSpace.FunctionSpacing">
        <properties>
            <property name="spacing" value="1"/>
            <property name="spacingBeforeFirst" value="0"/>
            <property name="spacingAfterLast" value="0"/>
        </properties>
    </rule>

    <!-- Проверяет что все языковые конструкции содержат один пробел между ними и их содержимым  -->
    <rule ref="Squiz.WhiteSpace.LanguageConstructSpacing"/>

    <!-- Проверяет наличие пробелов вокруг логических операторов -->
    <rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>

    <!-- Проверка, что перед оператором объекта и после него нет пробелов -->
    <rule ref="Squiz.WhiteSpace.ObjectOperatorSpacing">
        <properties>
            <property name="ignoreNewlines" value="true"/>
        </properties>
    </rule>

    <!-- Проверяет что перед точкой с запятой нет пробелов -->
    <rule ref="Squiz.WhiteSpace.SemicolonSpacing"/>

    <!--
    Проверяет на наличие ненужных пробелов.

    * Пробел в конце строки (EndLine)
    * Дополнительный пробел в начале файла (StartFile)
    * Дополнительный пробел в конце файла (EndFile)
    * Несколько пустых строк в функциях (EmptyLines)
    -->
    <rule ref="Squiz.WhiteSpace.SuperfluousWhitespace"/>

    <!--
        Проверяет, что элементы массива имеют отступ в 4 пробел

        Пример:
        $array = [
            'ok',
          'ng', // Array key not indented correctly; expected 4 spaces but found 2
        ];
    -->
    <rule ref="Generic.Arrays.ArrayIndent"/>

    <!--
        Запрещает синтаксис длинного массива.

        Пример:
        $ok = [];
        $ng = array(); // Short array syntax must be used to define arrays
    -->
    <rule ref="Generic.Arrays.DisallowLongArraySyntax"/>

    <!--
        Проверяет наличие пустых операторов PHP.

        * Две точки с запятой без исполняемого кода между ними
        * Пустая комбинация тегов открытия-закрытия PHP

        Пример:
        <?php
        ; // Empty PHP statement detected: superfluous semi-colon.
        ?>

        <?php ?> // Empty PHP open/close tag combination detected.
    -->
    <rule ref="Generic.CodeAnalysis.EmptyPHPStatement"/>

    <!--
        Обнаружение пустых утверждений. (try, catch, finally, do, else, elseif, for, foreach, if, switch, while)
        Также считается пустым, если полностью пустой или просто пустая строка или комментарий.

        Пример:
        if (true) { // Empty IF statement detected
            // empty
        }
    -->
    <rule ref="Generic.CodeAnalysis.EmptyStatement"/>

    <!--
        Обнаружение безусловных операторов if и elseif.
        Обнаружены условия, в которых установлены только истина или ложь.

        Пример:
        if (true) { // Avoid IF statements that are always true or false
            echo 'Hello';
        }
    -->
    <rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>

    <!--
        Обнаружение неиспользуемых параметров функции.
        Однако это не будет обнаружено, если содержимое функции пусто или содержит только комментарии.

        Пример:
        function hoge($hoge) { // The method parameter $hoge is never used
            echo 'Hello';
        }

        function fuga($fuga) {
        }
    -->
    <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>

    <!--
        Обнаруживает ненужные переопределенные методы, которые просто вызывают родителя.

        Пример:
        class Hoge
        {
            public function __construct()
            {
                echo 'Hello';
            }
        }

        class Fuga extends Hoge
        {
            public function __construct() // Possible useless method overriding detected
            {
                parent::__construct();
            }
        }
    -->
    <rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>


    <!--
        Убедитесь, что ваши блоки документов соответствуют базовому форматированию.

        Пример:
        /** */

        /** example
         */
    -->
    <rule ref="Generic.Commenting.DocComment">
        <exclude name="Generic.Commenting.DocComment.MissingShort"/>
        <exclude name="Generic.Commenting.DocComment.ShortNotCapital"/>
    </rule>

    <!--
        Запрещает использование условных выражений Йоды.

        Пример:
        $value = 10;

        if (100 === $value) { // Usage of Yoda conditions is not allowed; switch the　expression order
        }
    -->
    <rule ref="Generic.ControlStructures.DisallowYodaConditions"/>

    <!--
        Запрещает использовать устаревшие функции

        Пример:
        mbsplit('\s', 'hello world'); // Function mbsplit() has been deprecated
    -->
    <rule ref="Generic.PHP.DeprecatedFunctions"/>

    <!--
         Запрещает использовать суперглобальные переменные

        Пример:
        var_dump($_REQUEST); // The $_REQUEST superglobal should not be used; use $_GET, $_POST, or $_COOKIE instead
    -->
    <rule ref="Generic.PHP.DisallowRequestSuperglobal"/>
    <rule ref="SlevomatCodingStandard.Variables.DisallowSuperGlobalVariable"/>

    <!-- Запрещает использовать конструкцию goto -->
    <rule ref="Generic.PHP.DiscourageGoto"/>

    <!--
        Запрещает использовать префикс @ для подавления ошибок

        Пример:
        @fopen('hoge.txt', 'r'); // Silencing errors is discouraged; found: @fopen('hoge.txt'...
    -->
    <rule ref="Generic.PHP.NoSilencedErrors"/>

    <!--
        Проверка на наличие лишних пробелов в скобках

        Пример:
        $hoge = 'hoge';
        $fuga = ($hoge !== 'fuga' ); // Expected 0 space before close parenthesis; 1 found
    -->
    <rule ref="Generic.WhiteSpace.ArbitraryParenthesesSpacing"/>

    <!--
        Проверяет что вокруг квадратных скобок нет пробелов

        Пример:
        $array ['hoge']; // Space found before square bracket; expected "$array[" but found "$array ["
        $array[ 'huga']; // Space found after square bracket; expected "['huga'" but found "[ 'huga'"
    -->
    <rule ref="Squiz.Arrays.ArrayBracketSpacing"/>

    <!--
        Проверяет, соответствует ли имя файла имени класса, содержащегося в файле.

        Пример:
        class Hoge
        {
        }

        //название файла NoMatch
    -->
    <rule ref="Squiz.Classes.ClassFileName">
        <exclude-pattern>install/index.php</exclude-pattern>
    </rule>

    <!--
    Проверьте правильность выравнивания звездочек в комментариях к документации.

    Пример:
    /**
     *NoSpaceAfterStar
       * SpaceBeforeStar
     */
    class Hoge
    {
    }
    -->
    <rule ref="Squiz.Commenting.DocCommentAlignment"/>

    <!--
    Исключение из-за особенностей некоторых констант в bitrix
    -->
    <rule ref="Generic.NamingConventions.UpperCaseConstantName.ClassConstantNotUpperCase">
        <exclude-pattern>bootstrap.php</exclude-pattern>
    </rule>

    <!--
    Исключение из-за особенностей файлов установки модулей и компонентов в bitrix
    -->
    <rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
        <exclude-pattern>install/index.php</exclude-pattern>
        <exclude-pattern>/class.php</exclude-pattern>
        <exclude-pattern>/ajax.php</exclude-pattern>
    </rule>

    <!--
    Исключение из-за особенностей файлов установки модулей в bitrix
    -->
    <rule ref="Squiz.Classes.ValidClassName.NotCamelCaps">
        <exclude-pattern type="relative">/install/index.php*</exclude-pattern>
    </rule>

    <!--
    Исключение из-за особенностей файлов установки модулей и компонентов в bitrix
    -->
    <rule ref="PSR1.Files.SideEffects.FoundWithSymbols">
        <exclude-pattern>install/index.php</exclude-pattern>
        <exclude-pattern>/class.php</exclude-pattern>
        <exclude-pattern>/ajax.php</exclude-pattern>
    </rule>

    <!--
    Проверка длинны строки в 120 символов
    -->
    <rule ref="Generic.Files.LineLength.TooLong">
        <exclude-pattern>template/module</exclude-pattern>
    </rule>
</ruleset>
